home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1993-94, Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that the name of Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
- * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glx.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/keysym.h>
-
- /*
- * we'll define our own PI, could get it
- * from math.h, but i'm not in the mood
- */
- #define M_PI 3.14159265358979323846
-
- /*
- * some local functions
- */
- void drawScene(void);
- void drawcyl(void);
- void drawBox(void);
- void setMaterial(GLenum, float *, float *, float *, float *);
-
- /*
- * define some lighting properties
- */
- static float ambient[] = { 0.2, 0.2, 0.2, 1.0 };
- static float diffuse[] = { 0.6, 0.6, 0.6, 1.0 };
- static float specular[] = { 1.0, 1.0, 1.0, 1.0 };
- static float alm[] = { 0.1, 0.1, 0.1, 1};
- static float lpos[] = { 0, 0, 100, 0 };
- static float shininess[] = { 128.0 };
-
- /*
- * define material properties.
- */
- static float ambient2[] = { 0.4, 0.0, 0.4, 1.0 };
- static float diffuse2[] = { 0.7, 0.0, 0.7, 1.0 };
- static float specular2[] = { 1.0, 1.0, 1.0, 1.0 };
-
- float bamat[] = {.4, .4, .4, 1.0};
- float bdmat[] = { 0.8, .8, .8, 1.0};
- float bsmat[] = { .1, .1, .1, 1.0};
-
- float amat[] = {.1, .1, .2, 0.3};
- float dmat[] = { 0.3, .3, .5, 0.3};
- float smat[] = { 1.0, 1.0, 1.0, 0.3};
- float shin[] = { 128.0 };
-
- float amat2[] = {.1, .1, .1, 0.5};
- float dmat2[] = { .3690, .0, .165, 0.5};
- float smat2[] = { .8, .8, .8, 0.5};
-
-
- /*
- * the attribute list for the OpenGL visual.
- * we only request 1 bit for each color and depth, we get more
- * than 1 bit for each, i just put in for the minimum, the
- * server should return a visual that meets these requirements or
- * better...
- */
- static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- None };
-
- /*
- * the attribute list for the overlay OpenGL visual.
- * notice that we define 2 of them, GLX_LEVEL 2 and 1.
- * we will try to get an overlay visual (GLX_LEVEL 2). if we can't get one,
- * we will try to overlay planes (GLX_LEVEL 1)
- */
- static int al2[] = {GLX_LEVEL, 2, None };
-
- static int al3[] = {GLX_LEVEL, 1, None };
-
- /*
- * a convenience function, just waits for the window to map. this
- * is handy, since we don't want to risk OpenGL drawing into an
- * unmapped window, that would be bad...
- */
- static Bool WaitForNotify (Display *d, XEvent *e, char *arg)
- {
- return (e->type == MapNotify) && (e->xmap.window == (Window) arg);
- }
-
- /*
- * default window size...
- */
- #define WINSIZE 600
-
- /*
- * a few global variables
- */
- int WIRE_FRAME = 0;
- int TRANSPARENT = 0;
- int RESET = True;
- int WHITE_PIXEL_NUM;
-
- int xorigin, yorigin; /* window x and y locations */
- unsigned int width, height; /* window width and height */
- float rx, ry; /* adjusted x and y locations */
- Display *dpy; /* X Display */
- Window win; /* OpenGL X Window ID */
- Window owin; /* OpenGL overlay X Window ID */
- GLXContext cx; /* context for the OpenGL window */
- GLXContext ocx; /* context for the overlay OpenGL window */
-
- Window winList[3]; /* X window ID list, needed to map window
- colormaps */
-
-
- /*
- * main routine.
- */
- main()
- {
-
- XVisualInfo *vi; /* X Visual */
- Colormap cmap, ocmap; /* X Colormap */
- XSetWindowAttributes swa; /* X Window Attributes */
- XEvent event; /* X event */
- char xbuf[20]; /* character buffer */
- int nchar = 20; /* size of character buffer */
- KeySym key; /* keyboard key hit */
- XComposeStatus cs; /* X keyboard compose structure */
- XWindowAttributes winattrs; /* X Window attribute structure */
- XColor spix, pixel; /* X pixel structure */
- float fx, fy; /* adjusted x & y cursor positions */
-
-
- /*
- * open a connection to the local display
- */
- dpy = XOpenDisplay (0);
-
- /*
- * get an OpenGL main plane visual, if we fail, big problems,
- * exit...
- */
- if (!(vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList))) {
- printf("\n can't get requested visual type, bye...\n");
- exit(0);
- }
-
- /* create a GLX context */
- cx = (GLXContext) glXCreateContext (dpy, vi, None, GL_TRUE);
-
- /* create a colormap using this visual */
- cmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
- AllocNone);
-
- /* set up the window attributes and create an X Window */
- swa.colormap = cmap;
- swa.border_pixel = 1;
- swa.event_mask = StructureNotifyMask;
- win = XCreateWindow (dpy, RootWindow(dpy,vi->screen),
- 0, 0, WINSIZE, WINSIZE,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
-
- XMapWindow (dpy,win);
-
- /*
- * try to create an overlay window. first try for GLX_LEVEL 2, a visual
- * in the overlay planes. if that fails, go for GLX_LEVEL 1, a visual in
- * the popup planes. if that fails, game over...
- */
-
- if (!(vi = glXChooseVisual (dpy, DefaultScreen(dpy), al2))) {
-
- /*
- * overlay failed, try popup
- */
- fprintf(stderr, "bummer, can't get overlay visual, trying popup...\n");
-
- if (!(vi = glXChooseVisual (dpy, DefaultScreen(dpy), al3))) {
- /*
- * popup failed too, bummer
- */
- fprintf(stderr,
- "bummer, can't get requested popup visual either, bye...\n");
- exit(0);
- }
- else { /* got popup visual! */
- fprintf(stderr,"got popup visual!\n");
- }
- }
- else {
- fprintf(stderr, "got overlay visual!\n");
- }
-
- /*
- * create a GLX context for the overlay window
- */
- ocx = (GLXContext) glXCreateContext (dpy, vi, None, GL_TRUE);
-
- /*
- * create a colormap using this visual
- */
- ocmap = XCreateColormap (dpy, RootWindow(dpy, vi->screen), vi->visual,
- AllocNone);
-
- /*
- * set up window attributes and create a X Window with overlay visual
- */
- swa.colormap = ocmap;
- swa.border_pixel = 0;
- swa.win_gravity = UnmapGravity;
- swa.bit_gravity = NorthWestGravity;
- swa.background_pixel = BlackPixel(dpy, vi->screen);
-
- owin = XCreateWindow (dpy, win, 0, 0, WINSIZE, WINSIZE,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
-
- /*
- * map window
- */
- XMapWindow (dpy,owin);
-
-
- /*
- * wait for main planes window to map so that we can start drawing into
- * it.
- */
- XIfEvent(dpy, &event, WaitForNotify, (char *) win);
-
- /*
- * install the colormap windows property so that overlay colormap
- * takes hold when we move cursor into window
- */
- winList[0] = win;
- winList[1] = owin;
- XSetWMColormapWindows(dpy, win, winList, 2);
-
- /*
- * get the 'white' pixel value, we will need this
- * to set colormap index for overlay drawing
- */
- XAllocNamedColor(dpy, ocmap, "white", &spix, &pixel);
- WHITE_PIXEL_NUM = pixel.pixel;
-
- /*
- * connect the context to the main planes window
- */
- if (!glXMakeCurrent(dpy, win, cx) == GL_TRUE) {
- return 0;
- }
-
-
- /*
- * get the window size and location so that we can
- * make the cylinder track the mouse movements *somewhat* acurately
- */
-
- XGetWindowAttributes(dpy, win, &winattrs);
- xorigin = winattrs.x;
- yorigin = winattrs.y;
- width = winattrs.width;
- height = winattrs.height;
-
-
- /*
- * all right! finally some OpenGL stuff!!
- * enable zbuffer depth test
- */
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
-
- /*
- * set up projection matrix, perspective projection if you please...
- */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective((double) 450, (double) (width/(float)height),
- (double) .25, (double) 15.0);
-
- /*
- * ok, model transformations from now on...
- */
- glMatrixMode(GL_MODELVIEW);
-
- /*
- * set up lighting attributes
- */
- glLightfv(GL_LIGHT1, GL_POSITION, lpos);
- glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
- glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
- glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
-
-
- /*
- * set up light model attributes
- */
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
- glLightModelfv(GL_LIGHT_MODEL_AMBIENT, alm);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
-
- /*
- * turn on the light!
- */
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT1);
-
-
- /*
- * hit the model matrix with an initial translation, 3 units back in
- * Z direction to add a little spice...
- */
- glTranslatef(0., 0., -3.);
-
-
- /*
- * set X input stuff
- */
- XSelectInput(dpy, win, ExposureMask);
-
- XSelectInput(dpy, win, ExposureMask |StructureNotifyMask |
- ButtonPressMask | Button1MotionMask |
- SubstructureNotifyMask | KeyPressMask |
- KeyReleaseMask | ButtonReleaseMask );
-
- /*
- * do the same for overlay window
- */
- XSelectInput(dpy, owin, ExposureMask);
- XSelectInput(dpy, owin, ExposureMask |StructureNotifyMask |
- ButtonPressMask | Button1MotionMask |
- SubstructureNotifyMask | KeyPressMask |
- KeyReleaseMask | ButtonReleaseMask );
-
-
-
- /*
- * ready to go, print out instructions to the screen
- */
-
- printf("\npush leftmouse button and drag to move cylinder!\n");
- printf("\n 'o' key to toggle overlay drawing");
- printf("\n 't' key to toggle scene transparency");
- printf("\n 'Esc' key to quit\n");
- fflush(stdout);
-
-
- /*
- * the dreaded X event loop...
- */
- while (1) { /* loop forever... */
-
- XNextEvent(dpy, &event);
-
- switch (event.type) {
-
- case Expose:
- if (event.xexpose.count)
- continue;
- drawScene();
- if (!WIRE_FRAME) { /* have to manually clear overlay */
- /* since code is too 'dumb' to */
- /* redraw overlay in drawScene */
- glXMakeCurrent(dpy, owin, ocx);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
- break;
-
- case ConfigureNotify:
-
- /*
- * resize or reposition, so get pertinent window
- * info and update scene. don't forget to
- * resize overlay window!
- */
-
- XGetWindowAttributes(dpy, win, &winattrs);
- xorigin = winattrs.x;
- yorigin = winattrs.y;
- width = winattrs.width;
- height = winattrs.height;
- glXMakeCurrent(dpy, win, cx);
- glViewport(0, 0, width, height);
- drawScene();
-
- XResizeWindow(dpy, owin, width, height);
- glXMakeCurrent(dpy, owin, ocx);
- glViewport(0, 0, width, height);
- break;
-
-
- case KeyPress:
-
- XLookupString((XKeyEvent *) &event, xbuf, nchar, &key, &cs);
-
- switch (key) {
-
- case XK_Escape: /* quit */
- printf("\n bye...\n");
- exit(0);
- break;
-
- case XK_T: /* toggle scene transparency */
- case XK_t:
- TRANSPARENT = !TRANSPARENT;
- drawScene();
- break;
-
- case XK_O: /* toggle overlay drawing */
- case XK_o:
- WIRE_FRAME = !WIRE_FRAME;
- drawScene();
- break;
- }
-
- break;
-
-
- case MotionNotify:
- /*
- * get cursor position and rotate scene
- */
- fx = (float) event.xmotion.x;
- fy = (float) event.xmotion.y;
- rx = -500.0 * (2.0*(fy - yorigin)/height-1.0);
- ry = 500.0 * (2.0*(fx - xorigin)/width-1.0);
-
- drawScene();
- break;
-
- default:
- break;
-
- }
- }
-
- }
-
-
- /*
- * main scene drawing routine.
- */
- void
- drawScene()
- {
-
-
- if (!WIRE_FRAME) {
- /*
- * no wire frame, so update main planes scene.
- * set the main plane window as the current window to draw into,
- * clear the window and depth buffer
- */
- glXMakeCurrent(dpy, win, cx);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- /*
- * push down a new matrix onto the matrix stack. then apply
- * a couple of rotations
- */
- glPushMatrix();
- glRotatef((float) ry, 0., 1., 0.);
- glRotatef((float) -rx, 1., 0., 0.);
-
- /*
- * disable blending and turn on depth check
- */
- glDisable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ZERO);
- glDepthMask(1);
-
- /*
- * set up materials
- */
- setMaterial(GL_FRONT, ambient2, diffuse2, specular2, shininess);
- setMaterial(GL_BACK, bamat, bdmat, bsmat, shin);
-
- /*
- * scale down cylinder slightly
- */
- glScalef(.5, 1.0, .5);
- drawcyl();
-
- /*
- * pop matrix off of stack
- */
- glPopMatrix();
-
- /*
- * new matrix, apply same rotations
- */
- glPushMatrix();
-
- glRotatef((float) ry, 0., 1., 0.);
- glRotatef((float) -rx, 1., 0., 0.);
-
- /*
- * if transparency enabled, turn off depth check, enable blending
- */
- if (TRANSPARENT) {
- glDepthMask(0);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else { /* else no transparency */
- glDisable(GL_BLEND);
- glDepthMask(1);
- }
-
- /*
- * set up materials, draw cylinder
- */
- setMaterial(GL_FRONT, amat, dmat, smat, shin);
- setMaterial(GL_BACK, amat, dmat, smat, shin);
-
- drawcyl();
-
- /*
- * disable blending
- */
- if (TRANSPARENT)
- glDisable(GL_BLEND);
-
-
- /*
- * pop off matrix, swap buffers to show updated scene
- */
- glPopMatrix();
-
- glXSwapBuffers(dpy, win);
- }
-
- else {
-
- /*
- * draw into overlay window. make overlay window current, and
- * clear;
- */
-
- glXMakeCurrent(dpy, owin, ocx);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- /*
- * push down a matrix onto the stack, and apply rotations
- */
- glPushMatrix();
-
- glRotatef((float) ry, 0., 1., 0.);
- glRotatef((float) -rx, 1., 0., 0.);
-
- /*
- * draw the wire box, flush the graphics pipe, pop the matrix off
- * of the matrix stack
- */
- drawBox();
- glFlush();
-
- glPopMatrix();
-
- }
- }
-
-
- /*
- * routine to draw cylinder. note that normals are specified with
- * glNormal3fv() to take advantage of lighting.
- */
- void
- drawcyl()
- {
- double dy = .2;
- double theta, dtheta = 2*M_PI/20;
- double x, y, z;
- float n[3], v[3];
- int i, j;
-
- for (i = 0, y = -1; i < 10; i++, y += dy) {
- glEnable(GL_LIGHTING);
- glBegin(GL_TRIANGLE_STRIP);
- for (j = 0, theta = 0; j <= 20; j++, theta += dtheta) {
- if (j == 20) theta = 0;
- x = cos(theta);
- z = sin(theta);
- n[0] = x; n[1] = 0; n[2] = z;
- glNormal3fv(n);
- v[0] = x; v[1] = y; v[2] = z;
- glVertex3fv(v);
- v[1] = y + dy;
- glVertex3fv(v);
- }
- glEnd();
- }
- }
-
-
- /*
- * convenience function to set material properties
- */
- void
- setMaterial(GLenum face, float *ambient, float *diffuse,
- float *specular, float *shininess)
- {
- glMaterialfv(face, GL_AMBIENT, ambient);
- glMaterialfv(face, GL_DIFFUSE, diffuse);
- glMaterialfv(face, GL_SPECULAR, specular);
- glMaterialfv(face, GL_SHININESS, shininess);
- }
-
-
- /*
- * routine to draw the wire box in the overlay window. notice that
- * we use color index mode, glIndexi() to set colors here even though
- * the main plane window uses RGB
- */
- void
- drawBox()
- {
-
- float v[2];
-
- glIndexi(WHITE_PIXEL_NUM);
-
- glBegin(GL_LINE_LOOP);
- v[0] = v[1] = -.5;
- glVertex2fv(v);
- v[0] = .5;
- glVertex2fv(v);
- v[1] = .5;
- glVertex2fv(v);
- v[0] = -.5;
- glVertex2fv(v);
- glEnd();
-
-
-
- }
-
-
-
-